package com.rslai.commons.util;

import java.io.*;
import java.util.Vector;

/**
 * 处理文件、目录的工具类
 * Created by rslai on 2018/12/6.
 */
public class FileUtil {

    /**
     * <p>判断是否是文件</p>
     *
     * @param pathname  要判断的文件名
     * @return {@code true} 是文件
     */
    public boolean isFile(String pathname) {
        return new File(pathname).isFile();
    }

    /**
     * <p>判断是否是目录</p>
     *
     * @param pathname 要判断的目录
     * @return {@code true} 是目录
     */
    public boolean isDirectory(String pathname) {
        return new File(pathname).isDirectory();
    }

    /**
     * <p>判断文件或目录是否存在</p>
     *
     * @param pathname 要判断的文件名或目录
     * @return {@code true} 文件或目录存在
     */
    public boolean fileOrDirExists(String pathname) {
        return new File(pathname).exists();
    }

    /**
     * <p>删除一个文件或目录</p>
     *
     * @param pathname 要删除的文件名或路径
     * @return {@code true} 删除成功
     * @throws IOException io异常
     */
    public boolean delete(String pathname) throws IOException {
        File file = new File(pathname);
        if (file.exists()) {
            if (file.isDirectory()) {
                if (file.listFiles().length != 0) {
                    throw new IOException("指定删除的路径非空！" + pathname);
                }
            }
            if (file.delete()) {
                return true;
            } else {
                throw new IOException("指定删除的文件或路径失败！" + pathname);
            }
        }
        return true;
    }

    /**
     * <p>删除整个目录及目录下的所有文件</p>
     *
     * @param pathname 要删除的文件名或路径
     * @return {@code true} 删除成功
     */
    public boolean deleteTree(String pathname) {
        File file = new File(pathname);
        if (file.exists()) {
            if (file.isDirectory()) {
                File[] fileList = file.listFiles();
                for (File oneFile : fileList) {
                    if (oneFile.isDirectory()) {
                        try {
                            deleteTree(oneFile.getCanonicalPath());
                        } catch (IOException e) {
                        }
                    } else {
                        oneFile.delete();
                    }
                }
            }
            return file.delete();
        }
        return true;
    }

    /**
     * <p>创建目录，递归创建</p>
     *
     * @param pathname 目录全路径
     * @return {@code true} 创建成功
     * @throws IOException io异常
     */
    public boolean mkdirs(String pathname) throws IOException {
        File file = new File(pathname);
        file.mkdirs();
        if (file.exists()) {
            return true;
        } else {
            throw new IOException("创建指定目录失败！" + pathname);
        }
    }

    /**
     * <p>返回当前目录下的所有文件</p>
     *
     * @param pathname 目录全路径
     * @return 文件名列表
     */
    public Vector<String> list(String pathname) {
        Vector<String> fileList = new Vector<String>();
        File file = new File(pathname);
        if (file.exists() && file.isDirectory()) {
            list(file, fileList, false);
        }
        return fileList;
    }

    /**
     * <p>返回当前目录及其子目录下的所有文件</p>
     *
     * @param pathname 目录全路径
     * @return 文件名列表
     */
    public Vector<String> listAll(String pathname) {
        Vector<String> fileList = new Vector<String>();
        File file = new File(pathname);
        if (file.exists() && file.isDirectory()) {
            list(file, fileList, true);
        }
        return fileList;
    }

    /**
     * <p>返回目录中的所有文件名</p>
     *
     * @param file     File对象
     * @param fileList 保存找到的文件名
     * @param subdir   是否包含子目录
     * @return 文件名列表
     */
    private Vector<String> list(File file, Vector<String> fileList, boolean subdir) {
        File[] files = file.listFiles();
        if (null == files) {
            return fileList;
        }
        // 先存入所有文件
        for (File oneFile : files) {
            if (!oneFile.isDirectory()) {
                try {
                    fileList.add(oneFile.getCanonicalPath());
                } catch (IOException e) {
                }
            }
        }
        // 再遍历所有子目录
        for (File oneFile : files) {
            if (oneFile.isDirectory() && subdir) {
                list(oneFile, fileList, subdir);
            }
        }
        return fileList;
    }

    /**
     * <p>返回当前目录下的所有文件及目录</p>
     *
     * @param pathname 目录全路径
     * @return 文件名列表
     */
    public Vector<File> listFiles(String pathname) {
        Vector<File> fileList = new Vector<File>();
        File file = new File(pathname);
        if (file.exists() && file.isDirectory()) {
            listFiles(file, fileList, false);
        }
        return fileList;
    }

    /**
     * <p>返回当前目录及其子目录下的所有文件及目录</p>
     *
     * @param pathname 目录全路径
     * @return 文件名列表
     */
    public Vector<File> listFilesAll(String pathname) {
        Vector<File> fileList = new Vector<File>();
        File file = new File(pathname);
        if (file.exists() && file.isDirectory()) {
            listFiles(file, fileList, true);
        }
        return fileList;
    }

    /**
     * <p>返回目录中的所有文件及目录</p>
     *
     * @param file     File对象
     * @param fileList 保存找到的文件及目录
     * @param subdir   是否包含子目录
     * @return 文件名及目录列表
     */
    private Vector<File> listFiles(File file, Vector<File> fileList, boolean subdir) {
        File[] files = file.listFiles();
        if (null == files) {
            return fileList;
        }
        // 先存入所有文件
        for (File oneFile : files) {
            if (!oneFile.isDirectory()) {
                fileList.add(oneFile);
            }
        }
        // 再遍历所有子目录
        for (File oneFile : files) {
            if (oneFile.isDirectory()) {
                fileList.add(oneFile);
                if (subdir) {
                    listFiles(oneFile, fileList, subdir);
                }
            }
        }
        return fileList;
    }

    /**
     * <p>产生新文件名</p>
     *
     * @param pathname  原始文件名
     * @param insertStr 想在扩展名前插入的内容
     * @return 新文件名
     */
    public String createNewNname(String pathname, String insertStr) {
        pathname = pathname.replace("\\", "/");
        pathname = pathname.replaceAll("/{2,}", "/");

        // 拆出文件名
        String dir = "";
        String fileName = "";
        int lastSeparatorIndex = pathname.lastIndexOf("/");
        if (lastSeparatorIndex == -1) {
            fileName = pathname;
        } else {
            dir = pathname.substring(0, lastSeparatorIndex + 1);
            fileName = pathname.substring(lastSeparatorIndex + 1);
        }

        // 在文件扩展名前添加插入内容
        String newName;
        int pointIndex = fileName.lastIndexOf(".");
        if (pointIndex == -1) {
            newName = fileName + insertStr;
        } else {
            newName = fileName.substring(0, pointIndex) + insertStr + "." + fileName.substring(pointIndex + 1);
        }

        return dir + newName;
    }

    /**
     * <p>返回规范的文件或路径名</p>
     *
     * @param pathname 文件名或路径
     * @return 规范文件或路径名
     */
    public String getCanonicalPath(String pathname) {
        String name = null;
        try {
            name = (new File(pathname)).getCanonicalPath();
        } catch (IOException e) {
        }
        return name;
    }

    /**
     * <p>返回一个文件或路径的父路径，如果是跟路径则直接返回</p>
     *
     * <pre>
     *     getParent("/")   return "/"
     *     getParent("/lll/rrr")   return "/lll"
     *     getParent("c:\lll\l.txt")   return "c:\lll"
     * </pre>
     *
     * @param pathname 文件名或路径
     * @return 父路径
     */
    public String getParent(String pathname) {
        pathname = getCanonicalPath(pathname);
        String parent = new File(pathname).getParent();
        if (null == parent) {
            return pathname;
        } else {
            return parent;
        }
    }

    /**
     * <p>返回文件或目录的名称，不包括路径</p>
     *
     * <pre>
     *     getParent("/")   return ""
     *     getParent("/lll/rrr")   return "rrr"
     *     getParent("c:\lll\l.txt")   return "1.txt"
     * </pre>
     *
     * @param pathname 文件路径及名称
     * @return 返回不包括路径的文件或目录名称
     */
    public String getName(String pathname) {
        return new File(pathname).getName();
    }

    /**
     * <p>返回当前路径</p>
     *
     * @return 当前路径
     */
    public String getCurrentPath() {
        return System.getProperty("user.dir");
    }

    /**
     * <p>将指定字符串写入文件尾部</p>
     *
     * @param fileName 待写入的文件
     * @param str 待写入的字符串
     * @return {@code true} 写入成功
     * @throws IOException io错误
     */
    public boolean writeAppend(String fileName, String str) throws IOException {
        return write(fileName, str, true);
    }

    /**
     * <p>新建文件并将指定字符串写入</p>
     *
     * @param fileName 待写入的文件
     * @param str 待写入的字符串
     * @return {@code true} 写入成功
     * @throws IOException io错误
     */
    public boolean write(String fileName, String str) throws IOException {
        return write(fileName, str, false);
    }

    /**
     * <p>将指定字符串写入文件</p>
     *
     * @param fileName 待写入的文件
     * @param str      待写入的字符串
     * @param append   {@code true} 向文件尾部追加 {@code false} 新建文件写入
     * @return {@code true} 写入成功
     * @throws IOException io错误
     */
    private boolean write(String fileName, String str, boolean append) throws IOException {
        File file = new File(fileName);
        if (!file.exists()) {
            mkdirs(getParent(fileName));
        }
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, append)));
        out.write(str);
        out.close();
        return true;
    }

}
